package com.magicstone.common;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;

import javax.servlet.ServletContext;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;

import net.sf.jxls.exception.ParsePropertyException;
import net.sf.jxls.transformer.XLSTransformer;

public class JXLSHelper {
	private final static Logger logger = LogManager.getLogger(JXLSHelper.class);
	public static String TEMP = "template.xlsx";
	private static JXLSHelper _helper = null;
	public static final int MAX_ROWS = 1000;
	public static final String EXTENSION = "xlsx";
	public static final String SOURCE = "/jxls";
	public static final String TARGET = "/jxls/temp";

	private JXLSHelper(){
		
	}
	
	public static JXLSHelper getInstance(){
		if(null == _helper){
			_helper = new JXLSHelper();
		}
		return _helper;
	}
	
	public static String generateName(String ext){
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssS");
		String nowTime = sdf.format(new Date());
		return nowTime + ext;
	}
	
	public static String pathFix(String path){
		String pathFixed = path;
		int index = path.indexOf("WEB-INF");
		if(-1 == index){
			pathFixed = path + (path.endsWith("\\") ? "WEB-INF\\classes" : "\\WEB-INF\\classes");
			logger.debug("Path pre-fixed:" + path);
		}
		
		return pathFixed;
	}

	public boolean generateExcel(Map beans, File to){
		logger.debug(to.getAbsolutePath());
		boolean result = false;
		String from = TEMP;
		if(loadTemplate(from)){
			File fromFile = new File(from);
			result = generateExcel(fromFile.getAbsolutePath(), beans, to);
			fromFile.delete();
		}
		return result;
	}
	
	public static boolean generateExcel(String from, Map beans, File to) {
		logger.debug(from + ":" + to);
		mkDir(to.getAbsoluteFile().getParentFile());
		boolean result = true;
		XLSTransformer transformer = new XLSTransformer();
		try {
			transformer.transformXLS(from, beans, to.getAbsolutePath());
		} catch (ParsePropertyException e) {
			logger.error(e.getMessage());
			result = false;
		} catch (IOException e) {
			logger.error(e.getMessage());
			result = false;
		} catch (InvalidFormatException e) {
			logger.error(e.getMessage());
			result = false;
		}catch(Throwable e){
			logger.error(e.getMessage());
			result = false;
		}

		return result;
	}
	
	public String generateExcel4Web(ServletContext sc, String from, Map beans){
		String result = "";
		if(null != sc){
			logger.debug("1");
			String root = pathFix(sc.getRealPath("/"));
			logger.debug("2");
	
			String source = pathFix(sc.getRealPath(SOURCE));
			String target = pathFix(sc.getRealPath(TARGET));
			logger.debug("3");
			XLSTransformer transformer = new XLSTransformer();
			String sfrom = root + "\\jxls\\" + from;// 模板文件
			String sto = root + "\\jxls\\temp\\" + generateName(".xlsx");// 要生成的文件
			result = sto;
			logger.debug(sfrom);
			logger.debug(sto);
			logger.debug("Begin to generate excel...");
			generateExcel(sfrom, beans, new File(sto));
			logger.debug("Context path:" + sc.getContextPath());

			logger.debug("Web root:" + root);
	
			logger.debug("Template name:" + sfrom);
			logger.debug("Temporary excel file:" + sto);
		}
		return result;
	}

	public static String getCurrentDir(){
		File dir = new File(".");
		return dir.getAbsolutePath();
	}
	
	/*
	 * Load jxls template file from resource.
	 */
	public boolean loadTemplate(String dest){
		boolean result = false;
		try {
			InputStream is = this.getClass().getResourceAsStream("/jxls.xlsx");
				if(null != is){
				File desFile = new File(dest);
				mkDir(desFile.getAbsoluteFile().getParentFile());
				desFile.createNewFile();
				FileOutputStream fos = new FileOutputStream(desFile);
				int bytesRead;
				byte[] buf = new byte[4 * 1024]; // 4K buffer
				while ((bytesRead = is.read(buf)) != -1) {
					fos.write(buf, 0, bytesRead);
				}
				fos.flush();
				fos.close();
				is.close();
				result = true;
			}else{
				logger.debug("Fail to read template!");
			}
		} catch (IOException e) {
			logger.debug(e.getMessage());
		}
		return result;
	}
	
	public static boolean mkDir(File file) {
		file = file.getAbsoluteFile();
		boolean result = false;
		if(null != file){
			logger.debug(file.getAbsolutePath());
			File parent = file.getParentFile();
			if(null != parent){
				if (parent.exists()) {
					file.mkdir();
					result = true;
					logger.debug("create " + file.getAbsolutePath());
				} else {
					if(mkDir(parent)){
						file.mkdir();
						result = true;
						logger.debug("create " + file.getAbsolutePath());
					}
				}
			}else{
				logger.debug(file.getAbsolutePath() + ":" + file.getParent());
			}
		}
		return result;
	}
}
